package client;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;


public class WriteCommands extends Thread {

	private OutputStream os;
	private String commandData;
	private Monitor monitor;

	/**
	 * Thread for sending commands to the cameras
	 * @param os1 the output stream for camera 1
	 * @param monitor the client back-end monitor
	 */

	public WriteCommands(OutputStream outputStream, Monitor monitorIn) {
		os = outputStream;
		monitor = monitorIn;
		commandData = "";
	}

	/**
	 * Waits for and retrieves the next command to send, then sends it. 
	 */
	public void run() {
		while (true) {
			commandData = monitor.getSenddata();
			try {
				sendData(commandData.getBytes());
			} catch (IOException e) {
				System.out.println("Server offline...\n Message not sent:\n" + commandData);
				System.exit(-1);
			}
		}
	}
	
	/**
	 * Sends the pertinent data to the server
	 * @param documentData the array with the document data to send
	 * @throws IOException if an I/O error occurs. In particular, an IOException is thrown if the output stream is closed.
	 */
	private synchronized void sendData(byte documentData[]) throws IOException {
 		int bytes = 0;
		int command = Integer.parseInt("" + (char)documentData[0]);
		byte[] docData = new byte[documentData.length -1]; 
		System.arraycopy(documentData, 1, docData, 0, docData.length);
		bytes = docData.length;
		byte data[] = concat(concat(intToByteArray(command), intToByteArray(bytes)), docData);
		os.write(data);
		os.flush();
	}

	/**
	 * Helper method to create the header for the transmission protocol.
	 * Turns Integers into byte arrays.
	 * @param value of the Integer to transform
	 * @return the array
	 */
	private final byte[] intToByteArray(int value) {
		return new byte[] { (byte) (value >>> 24), (byte) (value >>> 16),
				(byte) (value >>> 8), (byte) value };
	}

	/**
	 * Helper method to create the header for the transmission protocol.
	 * Concatenates the arrays into a new array of appropriate size.
	 * @param first array
	 * @param second array
	 * @return finished array
	 */
	private byte[] concat(byte[] first, byte[] second) {
		byte[] result = Arrays.copyOf(first, first.length + second.length);
		System.arraycopy(second, 0, result, first.length, second.length);
		return result;
	}
}
